#!/usr/local/bin/perl
use CPANPLUS;
use Module::CoreList;
use Module::ScanDeps;
use FindBin qw($Script);
use File::Find;
use Data::Dumper;
use Cwd;
use strict;

my $cb      = new CPANPLUS::Backend;
my $perl = 5;
my $dat = "$Script.$$";

my %T;	# full path of test files (e.g. "*.t")
my %PM; # full path of module files (e.g. "*.pm")
my %MOD; # module name
my %REQ; # required modules
my %PATH; # required port paths
my %PERL; # PERL version scanned from ports, ('5.6.2', '5.8.8')
my $PORTSDIR = '/usr/ports';
my $INDEX = "$PORTSDIR/INDEX-7";
my %INDEX;

open(F, $INDEX) || die $!;
while(<F>)
{
  next if !m{\bperl-\d+};
  my $ver = $1 if m{^perl-([\d\.]+)};
  $PERL{$ver} = $ver if $ver;
  my @f = split('\|');
  my $pkgname = pkgname($f[0]);
  my $path = $f[1];
  $path =~ s{$PORTSDIR/}{};
  $INDEX{$pkgname} = $path;
}
close(F);
my $perl_min = (sort keys %PERL)[0];
my $perl_max = (sort keys %PERL)[-1];
chomp(my $WRKSRC = `make -V WRKSRC`);
my $cwd = getcwd();
`make extract`;
`cd $WRKSRC && perl Makefile.PL && make && cd $cwd`;
find(\&wanted, $WRKSRC);
# construct REQ{RUN} based on PM
my $PM = scan_deps(files => [ keys %PM ], recurse => 0, warn_missing => 1);
foreach my $entry (keys %$PM)
{
  next if $PM->{$entry}->{'type'} ne 'module';
  my $mod = $entry;
  $mod =~ s{\.pm$}{};
  $mod =~ s{/}{::}g;
  $REQ{'RUN'}{$mod} = 1;
}

# construct REQ{BUILD} based on T
my $T = scan_deps(files => [ keys %T ], recurse => 0, warn_missing => 1);
foreach my $entry (keys %$T)
{
  next if $T->{$entry}->{'type'} ne 'module';
  my $mod = $entry;
  $mod =~ s{\.pm$}{};
  $mod =~ s{/}{::}g;
  $REQ{'BUILD'}{$mod} = 1;
}

# construct MOD based on PM
foreach my $pm (keys %PM)
{
  $pm =~ s{^$WRKSRC/blib/lib/}{};
  $pm =~ s{^mach/}{};
  $pm =~ s{\.pm$}{};
  $pm =~ s{/}{::}g;
  $MOD{$pm} = 1;
}

# remove the ones that already shipped with the minimum core
foreach my $type (keys %REQ)
{
  foreach my $req (keys %{$REQ{$type}})
  {
    delete($REQ{$type}{$req}) if $MOD{$req};
    my $rel = level(Module::CoreList->first_release($req));
    delete($REQ{$type}{$req}) if ($rel > 0 && $rel <= level(5));
    $REQ{$type}{$req} = $rel;
  }
}

#printf("PERL_CONFIGURE=\t%s\n", $perl == 5 ? "yes" : "$perl+");

foreach my $type (reverse sort keys %REQ)
{
  my $out;
  foreach my $req (sort keys %{$REQ{$type}})
  {
    my $mod = $cb->module_tree($req);
    next if !$mod;
    my $pkg = $mod->package;
    next if $pkg =~ m{^perl-};
    my $pkgname = pkgname($pkg);
    my $path = $INDEX{$pkgname};
    next if !$path && $REQ{$type}{$req} < 500503;
    next if $PATH{$path};
    $PATH{$path} = 1;
    $out .= sprintf("%s>=%s:%s/%s ", $req, 0, '${PORTSDIR}', $path);
  }
  $out =~ s{\s+$}{};
  $out =~ s{ }{ \\\n\t\t}g;
  next if !$out;
  printf("PERL%s_DEPENDS=\t", $type eq 'BUILD' ? "_TEST" : "");
  print "$out\n";
}
`make clean`;

END {
  unlink($dat);
}
# END

sub level
{
  my $ver = shift;
  my ($x, $y, $z);
  ($x, $y, $z) = ($1, $2, $3) if $ver =~ m{^(\d+)\.?(\d{3})(\d*)$};
  ($x, $y, $z) = ($1, $2, $3) if $ver =~ m{^(\d+)\.(\d+)\.(\d+)$};
  ($x) = ($1) if $ver =~ m{^(\d+)$};
  return sprintf("%d%03d%02d", $x, $y, $z);
}

sub pkgname
{
  my $pkg = shift;
  if ($pkg =~ m{\.tar\.gz$})
  {
    $pkg =~ s{^}{p5-} if $pkg !~ m{^perl-};
    $pkg =~ s{\.tar\.gz$}{};
    $pkg =~ s{-perl}{};
  }
  $pkg =~ s{-v?[\d\.\w*,]+$}{};
  return $pkg;
}

sub wanted
{
  my $file = $_;
  my $dir = $File::Find::dir;
  my $path = $File::Find::name;
  push(@Module::ScanDeps::IncludeLibs, $path) if -d $path;
  return if ! -f $path;
  return if $path !~ m{\.(pm|t)$};
  return $PM{$path} = 1 if $path =~ m{^$WRKSRC/blib/.+.pm$};
  return $T{$path} = 1 if ($file =~ m{\.t$} || $file =~ m{test} || $path =~ m{/t/});
}
